/*
Color utilities.
- Copyright (C) 2005 Robert Lipe, robertlipe+source@gpsbabel.org
+ Copyright (C) 2005,2024 Robert Lipe, robertlipe+source@gpsbabel.org
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
*/
-#include "defs.h"
-#include <cstdlib>
+#include <assert.h> // for assert
+
+#include <QByteArray> // for QByteArray
+#include <QHash> // for QHash
+#include <QRegularExpression> // for QRegularExpression, QRegularExpressionMatch
+#include <QString> // for QString, QTypeInfo<>::isRelocatable
+#include <QtGlobal> // for qPrintable
+
+#include "defs.h" // for fatal, color_to_bbggrr
/*
* Colors derived from http://www.w3.org/TR/SVG/types.html#ColorKeywords
* same colors supported by X11.
*/
-static const struct {
- const char* cn;
+struct rgb_t {
unsigned char r;
unsigned char g;
unsigned char b;
-} color_table[] = {
- {"aliceblue", 240, 248, 255},
- {"antiquewhite", 250, 235, 215},
- {"aqua", 0, 255, 255},
- {"aquamarine", 127, 255, 212},
- {"azure", 240, 255, 255},
- {"beige", 245, 245, 220},
- {"bisque", 255, 228, 196},
- {"black", 0, 0, 0},
- {"blanchedalmond", 255, 235, 205},
- {"blue", 0, 0, 255},
- {"blueviolet", 138, 43, 226},
- {"brown", 165, 42, 42},
- {"burlywood", 222, 184, 135},
- {"cadetblue", 95, 158, 160},
- {"chartreuse", 127, 255, 0},
- {"chocolate", 210, 105, 30},
- {"coral", 255, 127, 80},
- {"cornflowerblue", 100, 149, 237},
- {"cornsilk", 255, 248, 220},
- {"crimson", 220, 20, 60},
- {"cyan", 0, 255, 255},
- {"darkblue", 0, 0, 139},
- {"darkcyan", 0, 139, 139},
- {"darkgoldenrod", 184, 134, 11},
- {"darkgray", 169, 169, 169},
- {"darkgreen", 0, 100, 0},
- {"darkgrey", 169, 169, 169},
- {"darkkhaki", 189, 183, 107},
- {"darkmagenta", 139, 0, 139},
- {"darkolivegreen", 85, 107, 47},
- {"darkorange", 255, 140, 0},
- {"darkorchid", 153, 50, 204},
- {"darkred", 139, 0, 0},
- {"darksalmon", 233, 150, 122},
- {"darkseagreen", 143, 188, 143},
- {"darkslateblue", 72, 61, 139},
- {"darkslategray", 47, 79, 79},
- {"darkslategrey", 47, 79, 79},
- {"darkturquoise", 0, 206, 209},
- {"darkviolet", 148, 0, 211},
- {"deeppink", 255, 20, 147},
- {"deepskyblue", 0, 191, 255},
- {"dimgray", 105, 105, 105},
- {"dimgrey", 105, 105, 105},
- {"dodgerblue", 30, 144, 255},
- {"firebrick", 178, 34, 34},
- {"floralwhite", 255, 250, 240},
- {"forestgreen", 34, 139, 34},
- {"fuchsia", 255, 0, 255},
- {"gainsboro", 220, 220, 220},
- {"ghostwhite", 248, 248, 255},
- {"gold", 255, 215, 0},
- {"goldenrod", 218, 165, 32},
- {"gray", 128, 128, 128},
- {"grey", 128, 128, 128},
- {"green", 0, 128, 0},
- {"greenyellow", 173, 255, 47},
- {"honeydew", 240, 255, 240},
- {"hotpink", 255, 105, 180},
- {"indianred", 205, 92, 92},
- {"indigo", 75, 0, 130},
- {"ivory", 255, 255, 240},
- {"khaki", 240, 230, 140},
- {"lavender", 230, 230, 250},
- {"lavenderblush", 255, 240, 245},
- {"lawngreen", 124, 252, 0},
- {"lemonchiffon", 255, 250, 205},
- {"lightblue", 173, 216, 230},
- {"lightcoral", 240, 128, 128},
- {"lightcyan", 224, 255, 255},
- {"lightgoldenrodyellow", 250, 250, 210},
- {"lightgray", 211, 211, 211},
- {"lightgreen", 144, 238, 144},
- {"lightgrey", 211, 211, 211},
- {"lightpink", 255, 182, 193},
- {"lightsalmon", 255, 160, 122},
- {"lightseagreen", 32, 178, 170},
- {"lightskyblue", 135, 206, 250},
- {"lightslategray", 119, 136, 153},
- {"lightslategrey", 119, 136, 153},
- {"lightsteelblue", 176, 196, 222},
- {"lightyellow", 255, 255, 224},
- {"lime", 0, 255, 0},
- {"limegreen", 50, 205, 50},
- {"linen", 250, 240, 230},
- {"magenta", 255, 0, 255},
- {"maroon", 128, 0, 0},
- {"mediumaquamarine", 102, 205, 170},
- {"mediumblue", 0, 0, 205},
- {"mediumorchid", 186, 85, 211},
- {"mediumpurple", 147, 112, 219},
- {"mediumseagreen", 60, 179, 113},
- {"mediumslateblue", 123, 104, 238},
- {"mediumspringgreen", 0, 250, 154},
- {"mediumturquoise", 72, 209, 204},
- {"mediumvioletred", 199, 21, 133},
- {"midnightblue", 25, 25, 112},
- {"mintcream", 245, 255, 250},
- {"mistyrose", 255, 228, 225},
- {"moccasin", 255, 228, 181},
- {"navajowhite", 255, 222, 173},
- {"navy", 0, 0, 128},
- {"oldlace", 253, 245, 230},
- {"olive", 128, 128, 0},
- {"olivedrab", 107, 142, 35},
- {"orange", 255, 165, 0},
- {"orangered", 255, 69, 0},
- {"orchid", 218, 112, 214},
- {"palegoldenrod", 238, 232, 170},
- {"palegreen", 152, 251, 152},
- {"paleturquoise", 175, 238, 238},
- {"palevioletred", 219, 112, 147},
- {"papayawhip", 255, 239, 213},
- {"peachpuff", 255, 218, 185},
- {"peru", 205, 133, 63},
- {"pink", 255, 192, 203},
- {"plum", 221, 160, 221},
- {"powderblue", 176, 224, 230},
- {"purple", 128, 0, 128},
- {"red", 255, 0, 0},
- {"rosybrown", 188, 143, 143},
- {"royalblue", 65, 105, 225},
- {"saddlebrown", 139, 69, 19},
- {"salmon", 250, 128, 114},
- {"sandybrown", 244, 164, 96},
- {"seagreen", 46, 139, 87},
- {"seashell", 255, 245, 238},
- {"sienna", 160, 82, 45},
- {"silver", 192, 192, 192},
- {"skyblue", 135, 206, 235},
- {"slateblue", 106, 90, 205},
- {"slategray", 112, 128, 144},
- {"slategrey", 112, 128, 144},
- {"snow", 255, 250, 250},
- {"springgreen", 0, 255, 127},
- {"steelblue", 70, 130, 180},
- {"tan", 210, 180, 140},
- {"teal", 0, 128, 128},
- {"thistle", 216, 191, 216},
- {"tomato", 255, 99, 71},
- {"turquoise", 64, 224, 208},
- {"violet", 238, 130, 238},
- {"wheat", 245, 222, 179},
- {"white", 255, 255, 255},
- {"whitesmoke", 245, 245, 245},
- {"yellow", 255, 255, 0},
- {"yellowgreen", 154, 205, 50},
+};
+
+static const QHash<QString, rgb_t> color_table = {
+ {"aliceblue", {240, 248, 255}},
+ {"antiquewhite", {250, 235, 215}},
+ {"aqua", { 0, 255, 255}},
+ {"aquamarine", {127, 255, 212}},
+ {"azure", {240, 255, 255}},
+ {"beige", {245, 245, 220}},
+ {"bisque", {255, 228, 196}},
+ {"black", { 0, 0, 0}},
+ {"blanchedalmond", {255, 235, 205}},
+ {"blue", { 0, 0, 255}},
+ {"blueviolet", {138, 43, 226}},
+ {"brown", {165, 42, 42}},
+ {"burlywood", {222, 184, 135}},
+ {"cadetblue", { 95, 158, 160}},
+ {"chartreuse", {127, 255, 0}},
+ {"chocolate", {210, 105, 30}},
+ {"coral", {255, 127, 80}},
+ {"cornflowerblue", {100, 149, 237}},
+ {"cornsilk", {255, 248, 220}},
+ {"crimson", {220, 20, 60}},
+ {"cyan", { 0, 255, 255}},
+ {"darkblue", { 0, 0, 139}},
+ {"darkcyan", { 0, 139, 139}},
+ {"darkgoldenrod", {184, 134, 11}},
+ {"darkgray", {169, 169, 169}},
+ {"darkgreen", { 0, 100, 0}},
+ {"darkgrey", {169, 169, 169}},
+ {"darkkhaki", {189, 183, 107}},
+ {"darkmagenta", {139, 0, 139}},
+ {"darkolivegreen", { 85, 107, 47}},
+ {"darkorange", {255, 140, 0}},
+ {"darkorchid", {153, 50, 204}},
+ {"darkred", {139, 0, 0}},
+ {"darksalmon", {233, 150, 122}},
+ {"darkseagreen", {143, 188, 143}},
+ {"darkslateblue", { 72, 61, 139}},
+ {"darkslategray", { 47, 79, 79}},
+ {"darkslategrey", { 47, 79, 79}},
+ {"darkturquoise", { 0, 206, 209}},
+ {"darkviolet", {148, 0, 211}},
+ {"deeppink", {255, 20, 147}},
+ {"deepskyblue", { 0, 191, 255}},
+ {"dimgray", {105, 105, 105}},
+ {"dimgrey", {105, 105, 105}},
+ {"dodgerblue", { 30, 144, 255}},
+ {"firebrick", {178, 34, 34}},
+ {"floralwhite", {255, 250, 240}},
+ {"forestgreen", { 34, 139, 34}},
+ {"fuchsia", {255, 0, 255}},
+ {"gainsboro", {220, 220, 220}},
+ {"ghostwhite", {248, 248, 255}},
+ {"gold", {255, 215, 0}},
+ {"goldenrod", {218, 165, 32}},
+ {"gray", {128, 128, 128}},
+ {"grey", {128, 128, 128}},
+ {"green", { 0, 128, 0}},
+ {"greenyellow", {173, 255, 47}},
+ {"honeydew", {240, 255, 240}},
+ {"hotpink", {255, 105, 180}},
+ {"indianred", {205, 92, 92}},
+ {"indigo", { 75, 0, 130}},
+ {"ivory", {255, 255, 240}},
+ {"khaki", {240, 230, 140}},
+ {"lavender", {230, 230, 250}},
+ {"lavenderblush", {255, 240, 245}},
+ {"lawngreen", {124, 252, 0}},
+ {"lemonchiffon", {255, 250, 205}},
+ {"lightblue", {173, 216, 230}},
+ {"lightcoral", {240, 128, 128}},
+ {"lightcyan", {224, 255, 255}},
+ {"lightgoldenrodyellow", {250, 250, 210}},
+ {"lightgray", {211, 211, 211}},
+ {"lightgreen", {144, 238, 144}},
+ {"lightgrey", {211, 211, 211}},
+ {"lightpink", {255, 182, 193}},
+ {"lightsalmon", {255, 160, 122}},
+ {"lightseagreen", { 32, 178, 170}},
+ {"lightskyblue", {135, 206, 250}},
+ {"lightslategray", {119, 136, 153}},
+ {"lightslategrey", {119, 136, 153}},
+ {"lightsteelblue", {176, 196, 222}},
+ {"lightyellow", {255, 255, 224}},
+ {"lime", { 0, 255, 0}},
+ {"limegreen", { 50, 205, 50}},
+ {"linen", {250, 240, 230}},
+ {"magenta", {255, 0, 255}},
+ {"maroon", {128, 0, 0}},
+ {"mediumaquamarine", {102, 205, 170}},
+ {"mediumblue", { 0, 0, 205}},
+ {"mediumorchid", {186, 85, 211}},
+ {"mediumpurple", {147, 112, 219}},
+ {"mediumseagreen", { 60, 179, 113}},
+ {"mediumslateblue", {123, 104, 238}},
+ {"mediumspringgreen", { 0, 250, 154}},
+ {"mediumturquoise", { 72, 209, 204}},
+ {"mediumvioletred", {199, 21, 133}},
+ {"midnightblue", { 25, 25, 112}},
+ {"mintcream", {245, 255, 250}},
+ {"mistyrose", {255, 228, 225}},
+ {"moccasin", {255, 228, 181}},
+ {"navajowhite", {255, 222, 173}},
+ {"navy", { 0, 0, 128}},
+ {"oldlace", {253, 245, 230}},
+ {"olive", {128, 128, 0}},
+ {"olivedrab", {107, 142, 35}},
+ {"orange", {255, 165, 0}},
+ {"orangered", {255, 69, 0}},
+ {"orchid", {218, 112, 214}},
+ {"palegoldenrod", {238, 232, 170}},
+ {"palegreen", {152, 251, 152}},
+ {"paleturquoise", {175, 238, 238}},
+ {"palevioletred", {219, 112, 147}},
+ {"papayawhip", {255, 239, 213}},
+ {"peachpuff", {255, 218, 185}},
+ {"peru", {205, 133, 63}},
+ {"pink", {255, 192, 203}},
+ {"plum", {221, 160, 221}},
+ {"powderblue", {176, 224, 230}},
+ {"purple", {128, 0, 128}},
+ {"red", {255, 0, 0}},
+ {"rosybrown", {188, 143, 143}},
+ {"royalblue", { 65, 105, 225}},
+ {"saddlebrown", {139, 69, 19}},
+ {"salmon", {250, 128, 114}},
+ {"sandybrown", {244, 164, 96}},
+ {"seagreen", { 46, 139, 87}},
+ {"seashell", {255, 245, 238}},
+ {"sienna", {160, 82, 45}},
+ {"silver", {192, 192, 192}},
+ {"skyblue", {135, 206, 235}},
+ {"slateblue", {106, 90, 205}},
+ {"slategray", {112, 128, 144}},
+ {"slategrey", {112, 128, 144}},
+ {"snow", {255, 250, 250}},
+ {"springgreen", { 0, 255, 127}},
+ {"steelblue", { 70, 130, 180}},
+ {"tan", {210, 180, 140}},
+ {"teal", { 0, 128, 128}},
+ {"thistle", {216, 191, 216}},
+ {"tomato", {255, 99, 71}},
+ {"turquoise", { 64, 224, 208}},
+ {"violet", {238, 130, 238}},
+ {"wheat", {245, 222, 179}},
+ {"white", {255, 255, 255}},
+ {"whitesmoke", {245, 245, 245}},
+ {"yellow", {255, 255, 0}},
+ {"yellowgreen", {154, 205, 50}},
};
/*
* Functions for converting human-readable colors to BBGGRR value.
- * Substantial optimization opportunities remain.
*/
-static int HexDigit(char hex)
-{
- const char* Digits = "0123456789ABCDEF";
- const char* digits = "0123456789abcdef";
- const char* ofs = strchr(digits, hex);
- if (ofs) {
- return ofs-digits;
- }
-
- ofs = strchr(Digits, hex);
- if (ofs) {
- return ofs-Digits;
- }
- return 0;
-}
-
-static int HexByte(const char* hex)
-{
- int b = (HexDigit(hex[0])<<4)+HexDigit(hex[1]);
- return b;
-}
/*
* Given an input of the form:
*/
int
-color_to_bbggrr(const char* cname)
+color_to_bbggrr(const QString& cname)
{
- char* ep;
-
- int color_num = strtol(cname, &ep, 10);
+ bool ok;
+ int color_num = cname.toInt(&ok);
- if (ep != cname) {
+ if (ok) {
return color_num;
}
- if (cname[0] == '#') {
- color_num = (HexByte(cname+1)) + // red
- (HexByte(cname+3)<<8) + // green
- (HexByte(cname+5)<<16); // blue
- return color_num;
+ static const QRegularExpression re("^#(?<red>[[:xdigit:]]{2})(?<green>[[:xdigit:]]{2})(?<blue>[[:xdigit:]]{2})$");
+ assert(re.isValid());
+ if (QRegularExpressionMatch match = re.match(cname); match.hasMatch()) {
+ return (match.captured("red").toInt(nullptr, 16) +
+ (match.captured("green").toInt(nullptr, 16) << 8) +
+ (match.captured("blue").toInt(nullptr, 16) << 16));
}
- for (auto i : color_table) {
- if (0 == case_ignore_strcmp(cname, i.cn)) {
- return (i.b << 16) +
- (i.g << 8) +
- i.r;
- }
+ if (color_table.contains(cname)) {
+ auto entry = color_table.value(cname);
+ return (entry.b << 16) + (entry.g << 8) + entry.r;
}
- fatal("unrecognized color name %s\n", cname);
+ fatal("unrecognized color name %s\n", qPrintable(cname));
return -1;
}